package apidocs;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import play.Play;
import utils.ApiUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Created by zhangzc on 4/1/17.
 */
public class SearchEngine {

    public static void search(List<SearchResult> resultList, int max, String q){
        doSearchApiClass(resultList, max - resultList.size(), q);
        doSearchApiJson(resultList, max - resultList.size(), q);
    }

    private static void doSearchApiClass(List<SearchResult> resultList, int remain, String q){
        if(remain <= 0){
            return;
        }

        List<Class> apiClassList = ApiUtil.getPermApiList(Play.classloader.getAnnotatedClasses(ApiService.class));

        apiClassList.forEach(apiClass ->{
            ApiService apiService = XJavaExtensionForApi.getApiService(apiClass);
            List<Method> methods = XJavaExtensionForApi.getApiActions(apiClass);
            methods.forEach(m->{
                Api api = XJavaExtensionForApi.getApiAction(m);
                String name = api.name();
                String url = XJavaExtensionForApi.getActionAsUrl(m, apiClass);
                if(StringUtils.containsIgnoreCase(name, q)
                        || StringUtils.containsIgnoreCase(url, q)){
                    SearchResult searchResult = new SearchResult();
                    searchResult.title = apiService.value() +'-' + api.name();
                    searchResult.url = "/@apidoc/api/"+apiClass.getCanonicalName()+"/"+m.getName();
                    searchResult.type = 0;
                    resultList.add(searchResult);
                    return;
                }

            });
        });

        List<Class> beanClassList = Play.classloader.getAnnotatedClasses(ApiResult.class);

        beanClassList.forEach(beanClass ->{
            ApiResult apiResult = XJavaExtensionForApi.getApiResult(beanClass);
            List<Field> fields = XJavaExtensionForApi.getApiResultField(beanClass);
            for(Field m: fields){
                ApiResultField apiResultField = XJavaExtensionForApi.getApiResultField(m);
                String beanName = apiResult != null ? apiResult.value() : beanClass.getSimpleName();
                String field = m.getName();
                String fieldName = apiResultField != null ? apiResultField.value() : m.getName();

                if(StringUtils.containsIgnoreCase(beanName, q)
                        || StringUtils.containsIgnoreCase(field, q)
                        || StringUtils.containsIgnoreCase(fieldName, q)){
                    SearchResult searchResult = new SearchResult();
                    searchResult.title = beanName;
                    searchResult.url = "/@apidoc/class/"+beanClass.getCanonicalName();
                    searchResult.type = 1;
                    resultList.add(searchResult);
                    break;
                }
            }
        });

    }

    private static void doSearchApiJson(List<SearchResult> resultList, int remain, String q) {
        if(remain <= 0){
            return;
        }

        JSONObject apiJson = ApiUtils.getApiJson();


        apiJson.getJSONArray("api_services").forEach(service ->{
            JSONObject serviceObject = (JSONObject) service;
            serviceObject.getJSONArray("apis").forEach(api ->{
                JSONObject apiObject = (JSONObject) api;
                //1. 搜索URL
                if(StringUtils.containsIgnoreCase(apiObject.getString("url"), q)){
                    SearchResult searchResult = new SearchResult();
                    searchResult.title = serviceObject.getString("title") +'-' +apiObject.getString("title");
                    searchResult.url = "/@apidoc/api_json/service/"+serviceObject.getString("name")+"/"+apiObject.getString("name");
                    searchResult.type = 0;
                    resultList.add(searchResult);
                }
                //2. 搜索API
                if(StringUtils.containsIgnoreCase(apiObject.getString("title"), q)){
                    SearchResult searchResult = new SearchResult();
                    searchResult.title = serviceObject.getString("title") +'-' +apiObject.getString("title");
                    searchResult.url = "/@apidoc/api_json/service/"+serviceObject.getString("name")+"/"+apiObject.getString("name");
                    searchResult.type = 0;
                    resultList.add(searchResult);
                }
            });
            //3. 搜索API category
            if(StringUtils.containsIgnoreCase(serviceObject.getString("title"), q) && !serviceObject.getJSONArray("apis").isEmpty()){
                JSONObject api = serviceObject.getJSONArray("apis").getJSONObject(0);
                SearchResult searchResult = new SearchResult();
                searchResult.title = serviceObject.getString("title");
                searchResult.url = "/@apidoc/api_json/service/"+serviceObject.getString("name")+"/"+api.getString("name");
                searchResult.type = 0;
                resultList.add(searchResult);
            }
        });
        //4. 搜索java bean
        JSONObject beansObject = apiJson.getJSONObject("beans");
        beansObject.keySet().forEach(k->{
            if(StringUtils.containsIgnoreCase(k, q)){
                JSONObject beanObject = beansObject.getJSONObject(k);
                if(beanObject != null){
                    SearchResult searchResult = new SearchResult();
                    searchResult.title = beanObject.getString("title");
                    searchResult.url = "/@apidoc/api_json/bean/" + k;
                    searchResult.type = 1;
                    resultList.add(searchResult);
                }
            }
        });

    }
}
